import { pushTarget, popTarget } from './dep';
import { nextTick } from '../utils/nextTick';
import { callHook } from "../vnode/lifecycle";
let id = 0;
class Watcher {
  constructor(vm, updateComponent, cb, options){
    this.vm = vm;
    this.expOrfn = updateComponent;
    this.cb = cb;
    this.options = options;
    this.user = options.user;
    this.lazy = this.dirty = options.lazy;
    this.id = id++;
    this.deps = [];
    this.depsId = new Set();
    if (typeof updateComponent === 'function'){
      this.getter = updateComponent; // 更新视图或者收集变量添加watcher
    } else {
      this.getter = function(){
        let path = this.expOrfn.split('.');
        let obj = vm;
        for(let i=0; i< path.length; i++) {
          obj = obj[path[i]]
        }
        return obj
      }
    }
    // 保存watch的初始值
    this.value = this.lazy ? void 0 : this.get(); // 保存watch初始值
  }
  addDep(dep){
    //  去重
    let id = dep.id;
    if (!this.depsId.has(id)) {
      this.deps.push(dep);
      this.depsId.add(id);
      dep.addSub(this);
    }
  }
  evaluate(){
    this.value = this.get();
    this.dirty = false;
  }
  depend(){
    let i = this.deps.length;
    while(i--) {
      this.deps[i].depend()
    }
  }
  run(){
    let value = this.get();
    let oldValue = this.value;
    this.value = value;
    // 执行handler
    if (this.user) {
      this.cb.call(this.vm, value, oldValue);
    } else {
      this.cb();
    }
  }
  // 初次渲染
  get(){
    pushTarget(this); // 给dep添加watcher
    const value = this.getter();
    popTarget(); // 给dep添加watcher
    return value;
  }
  // 更新的方法
  update(){
    // 不要数据更新后每次都调用， get方法会重新渲染
    // 缓存
    if (this.lazy) {
      this.dirty = true;
    } else {
      queueWatcher(this);
    }
    // this.get();
  }
}

let queue = []; // 将需要批量更新的watcher存放到一个队列中
let has = {};
let pending = false;

function flushWatcher(){
  let watcher;
  queue.forEach(item => {
    if (item.user) item.run();
    else watcher = item;
  });
  watcher.run();
  queue = [];
  has = {};
  pending = false
}
function queueWatcher(watcher){
  let id = watcher.id; // 每一个组件都是同一个watcher
  // 去重
  if (!has[id]) {
    // 队列处理
    queue.push(watcher);
    has[id] = true;
    // 防抖
    if (!pending) {
      nextTick(flushWatcher);
    }
    pending = true;
  }
}

// 收集依赖， dep, watcher, data
// dep: 和data的属性一一对应
// watcher： 在视图中用几个就有几个wacher
// dep和wacher: 一对多

export default Watcher